在有限的時間中,要學會一個前端框架不容易,也沒有一個框架是萬能的,但總要有個開始,筆者在進幾年一直在 extjs 的世界打滾,已有三四年的經驗,最近負責的專案除了使用 extjs,後端使用 grails,發現好處多多,就開發過程中的經驗與大家分享,從實際的例子還有兩個框架遇到得整合問題一一介紹
使用 extjs 一定要會用它的 query component,使用起來有點類似 css selector,jquery 也是類似的概念,有些選擇語法意義是相同的,不管是在定義 controller,或是在 binding event 的時候都會用到他,筆者找到一篇中國朋友寫的 query component 介紹,藉由他的文章進行介紹,連結如下:ExtJs ComponentQuery
根據元件 id 來 query,具有唯一性。前面以 # 號來代表, 取得 itemid 或者 id 符合的元件,範ExtJs ComponentQuery例如下:
var panel = Ext.ComponentQuery.query('#panel');
根據 xtype 來選擇,可選擇前面是否以 '.' 來標示,或者沒有任何符號也代表 xtype 查詢,如:
var cmp= Ext.ComponentQuery.query('gridpanel');
var cmp= Ext.ComponentQuery.query('.gridpanel');
如果我們要找某個類型下面的所擁有的元件 ID 或 itemid,我們可以這樣下
panel#myPanel
代表我要查詢 xtype 為 panel 底下有元件 id 為 myPanel
根據元件的屬性來選擇,舉例來說:
回傳擁有 iconCls 屬性的 Ext.Button 的實例:
var btnOk= Ext.ComponentQuery.query('button[iconCls]');
其中如果 iconCls 等於 null 或是 false 都視為不符合條件。
除此只外也可以判斷屬性指定特定的值,如下:
var btnOk= Ext.ComponentQuery.query('button[text = "ok"]');
取得 text 屬性為 'ok' 的 Ext.Button 的。
值得注意的是,屬性可以是任何自定義屬性:
Ext.create("Ext.Panel" , {
myAttribute: "helloWorld"
});
Ext.ComponentQuery.query('panel[myAttribute= "helloWorld"]');
如上面的例子,自己定義的屬性也可以作為判斷。
用來選擇特定容器或容器組的後代,後代選擇器由兩個常用選擇器,中間加一個空格表示。其中前面的選擇器選擇父元件,後面的選擇器選擇後代元件,範例如下:
取得所有 id 為 'myCt' 中的 Ext.Panel:
var panelsWithinmyCt = Ext.ComponentQuery.query('#myCt panel');
E F All descendant Components of E that match F (遞歸向下查詢所有可以符合的元件)
請注意這個選擇器與後代選擇器的區別,子選擇器(child selector)僅是指它的**直接後代**,而後代選擇器是作用於所有子後代元件。後代選擇器通過空格來進行選擇,而子選擇器是通過'>'進行選擇,範例如下:
取得所有 id 為 'myCt' 的 container 中的直接子元件 Ext.Panel :
var directChildPanel = Ext.ComponentQuery.query('#myCt > panel');
E > F All direct children Components of E that match F (查詢直接後代,其他非直接的則不符合)
參考下面範例來了解對應關係:
Ext.create("Ext.Panel" , {
itemId: "myCt" ,
itmes:[{
xtype: "panel" ,
html : "我是 myCt 的直接後代,也是 myCt 的後代" ,
itmes: [{
xtype: "panel" ,
html : "我是 myCt 的後代,但不是直接後代" ,
}]
}]
});
查找給定元素的父容器(遞迴向上查找所有符合的元素)。
E ^ F All parent Components of E that match F
Ext.ComponentQuery.query('textfield ^ form');
~=:符合完整的字串,以空白字元分開,假設我們有兩個元件:
Ext.create('Ext.panel.Panel' , {
cls: 'foo-cls my-cls bar-cls'
});
Ext.create( 'Ext.window.Window' , {
cls: 'my-cls'
});
下述查詢都會符合:
Ext.ComponentQuery.query('panel[cls~=my-cls]');
^=:開頭符合的屬性,如同 stratWith
$=:結尾符合的屬性,如同 endWith
*=:任何地方只要符合都算,如同 indexOf
@:只查詢使用類別的屬性,不會去查詢 extend 的父類別的屬性,使用方式:
Ext.ComponentQuery.query('panel[@collapsed=false]')
符合同時滿足多個條件的符合表達式,AND:
Ext.ComponentQuery.query('panel[cls~=my-cls][floating=true][title$="sales data"]');
符合用 ',' 逗號分隔的滿足任意一個條件的元件,OR:
Ext.ComponentQuery.query('field[fieldLabel^=User], field[fieldLabel*=password]');
查詢滿足條件的第一個元素,:first
:
Ext.ComponentQuery.query('panel > button:first');
查詢滿足條件的最後一個元素,:last
:
Ext.ComponentQuery.query('form[title=Profile] field:last');
取得可以獲得焦點的元件,:focusable
:
panel . down ( ':focusable' ). focus ();
符合相反的結果,:not
:
取得所有field但是xtype不是hiddenfield的元件
form . query ( 'field:not( hiddenfield )' );
其中 hiddenfield
部分可以放任何表達式如 title^=hello
指定每間隔多少的元件,:nth-child
:
透過範例可以較清楚如何使用此種 selector
//找出奇數的元件
form.query('field:nth-child(2n+1)');
//也可以使用關鍵字 :nth-child(odd)
//找出偶數的元件
form.query('field:nth-child(2n)');
//也可以使用關鍵字:nth-child(even)
//找出 3 倍數的元件
form.query('field:nth-child(3n)');
從 extjs component.query API 中,我們可以看到參數的使用為:query( selector, [root] )
其中 root 為選用,指的是要從哪個 Container 的範圍開始進行查詢,雖然是選用,強烈建議最好都要設置,如此一來在執行查詢時,extjs 在小範圍進行查詢,總比全域搜尋來的快,所以我們可以這樣執行:
var btnRefresh = Ext.ComponentQuery.query('#btnRefresh', container);
使用 Ext.ComponentQuery 來進行查詢,又或者,我們可以直接對某個 container 進行 query
var btnRefresh = container.query('#btnRefresh');
效果跟第一種方式一樣,都是區域性的元件 query。
更精確的定義,可以參考官方的 API 說明,如每個函式的連結。
down([selector]):取得第一個的子元件
child([selector]):取得第一個直接子元件
up([selector],[limit]):取得最接近的 container。
搞懂 compnent query 可以讓你在 extjs 的世界事半工倍,而且一點也不難的。
Ext JS 教學內容由思創軟體提供,共同作者 @lyhcode 與 @smlsun 目前在校園及企業從事 JavaScript(含 Node.js, Ext JS)與 Java(含 Groovy, Grails, Gradle) 教育訓練及顧問工作。